/*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#include <sourcemod>
#include <sdktools>
#include <l4d_stocks>
#include <l4d_weapon_stocks>
#include <sdkhooks>

#include "macros.sp"
#include "helpers.sp"

#define MELEE                   0
#define DEAGLE                  1

#define SHOTGUN                 1
#define SNIPE                   2
#define GL                      3
#define AK47                    4
#define RIFLE                   0
#define NOTHING                 -1

#define CVAR_FLAGS 		FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_NOTIFY

new g_iMeleeClassCount = 0;
new String:g_sMeleeClass[16][32];
new Handle:build[MAXSURVIVORS];
new Handle:cvar_melee = INVALID_HANDLE;
new bool:build_used[MAXSURVIVORS] = {false, ...};
new build_second[MAXSURVIVORS] = { -1, ...};

new bool:started = false;

public OnPluginStart()
{
	build[0] = CreateConVar("l4d2_givestuff_1", "1", "Build 1, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true, 0.0, true ,5.0);
	build[1] = CreateConVar("l4d2_givestuff_2", "1", "Build 2, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS,true, 0.0,true, 5.0);
	build[2] = CreateConVar("l4d2_givestuff_3", "2", "Build 3, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true, 0.0,true, 5.0);
	build[3] = CreateConVar("l4d2_givestuff_4", "2", "Build 4, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true,0.0, true, 5.0);
	build[4] = CreateConVar("l4d2_givestuff_5", "3", "Build 5, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true,0.0, true, 5.0);
	build[5] = CreateConVar("l4d2_givestuff_6", "3", "Build 6, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true,0.0, true, 5.0);
	build[6] = CreateConVar("l4d2_givestuff_7", "4", "Build 7, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true,0.0, true, 5.0);
	build[7] = CreateConVar("l4d2_givestuff_8", "4", "Build 8, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true,0.0, true, 5.0);
	build[8] = CreateConVar("l4d2_givestuff_9", "0", "Build 9, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true, 0.0, true, 5.0);
	build[9] = CreateConVar("l4d2_givestuff_10", "0", "Build 10, 0=Rifle, 1=Shotgun, 2=Snipe, 3=Grenade Launcher, 4=AK", CVAR_FLAGS, true,0.0, true, 5.0);

	cvar_melee = CreateConVar("l4d2_givestuff_melee", "8", "How many melee to give", CVAR_FLAGS, true,0.0, true, 10.0);

	AutoExecConfig(true, "l4d2_givestuff");

	HookEvent("round_start", Event_OnRoundStart, EventHookMode_Post);
	HookEvent("round_end", Event_RoundEnd);
	HookEvent("player_left_start_area", Event_PlayerLeaveArea);
	HookEvent("round_start_pre_entity", Event_RoundStartPreEnt);
}

public OnMapStart()
{	

	/*precache all melee models for all map*/
	PrecacheModel( "models/weapons/melee/v_bat.mdl", true );
	PrecacheModel( "models/weapons/melee/v_cricket_bat.mdl", true );
	PrecacheModel( "models/weapons/melee/v_crowbar.mdl", true );
	PrecacheModel( "models/weapons/melee/v_electric_guitar.mdl", true );
	PrecacheModel( "models/weapons/melee/v_fireaxe.mdl", true );
	PrecacheModel( "models/weapons/melee/v_frying_pan.mdl", true );
	PrecacheModel( "models/weapons/melee/v_golfclub.mdl", true );
	PrecacheModel( "models/weapons/melee/v_katana.mdl", true );
	PrecacheModel( "models/weapons/melee/v_machete.mdl", true );
	PrecacheModel( "models/weapons/melee/v_tonfa.mdl", true );
	
	PrecacheModel( "models/weapons/melee/w_bat.mdl", true );
	PrecacheModel( "models/weapons/melee/w_cricket_bat.mdl", true );
	PrecacheModel( "models/weapons/melee/w_crowbar.mdl", true );
	PrecacheModel( "models/weapons/melee/w_electric_guitar.mdl", true );
	PrecacheModel( "models/weapons/melee/w_fireaxe.mdl", true );
	PrecacheModel( "models/weapons/melee/w_frying_pan.mdl", true );
	PrecacheModel( "models/weapons/melee/w_golfclub.mdl", true );
	PrecacheModel( "models/weapons/melee/w_katana.mdl", true );
	PrecacheModel( "models/weapons/melee/w_machete.mdl", true );
	PrecacheModel( "models/weapons/melee/w_tonfa.mdl", true );
	
	PrecacheGeneric( "scripts/melee/baseball_bat.txt", true );
	PrecacheGeneric( "scripts/melee/cricket_bat.txt", true );
	PrecacheGeneric( "scripts/melee/crowbar.txt", true );
	PrecacheGeneric( "scripts/melee/electric_guitar.txt", true );
	PrecacheGeneric( "scripts/melee/fireaxe.txt", true );
	PrecacheGeneric( "scripts/melee/frying_pan.txt", true );
	PrecacheGeneric( "scripts/melee/golfclub.txt", true );
	PrecacheGeneric( "scripts/melee/katana.txt", true );
	PrecacheGeneric( "scripts/melee/machete.txt", true );
	PrecacheGeneric( "scripts/melee/tonfa.txt", true );

	GetMeleeClasses();
}

clear_used_build()
{
	new counter=0;
	for(new i=0; i<10; i++)
	{
		build_used[i] = false;
		/*init % of melee and deagle*/
		if(counter < GetConVarInt(cvar_melee))
		{
			build_second[i] = MELEE;
		}
		else
		{
			build_second[i] = DEAGLE;
		}

		counter++;
	}
}


public OnEntitySpawned(entity)
{

	if(started)
		return;

	if(IsValidSurvivor(entity)) 
	{
		new Float:time = GetRandomFloat(3.0, 5.0);
                CreateTimer(time, give_basic_stuff, entity, TIMER_FLAG_NO_MAPCHANGE); //will keep only real client
	}
}

public OnClientPutInServer(client)
{
	if(IsValidClient(client))
		SDKHook(client, SDKHook_SpawnPost, OnEntitySpawned)

}

public OnClientDisconnect(client)
{
	if(IsValidClient(client))
		SDKUnhook(client, SDKHook_SpawnPost, OnEntitySpawned)

}
public OnMapEnd()
{
	started = false;
}


public Event_PlayerLeaveArea(Handle:event, const String:name[], bool:dontBroadcast)
{
	started = true;
}
public Event_OnRoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
	started = false;
}

public Event_RoundStartPreEnt(Handle:event, const String:name[], bool:dontBroadcast)
{
	clear_used_build();
}


public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
	started = false;
}

public Action:give_basic_stuff(Handle:timer, any:client)
{

	if(!IsValidSurvivorAlive(client))
		return;

	new Meds = GetPlayerWeaponSlot(client, 4);
	if (Meds != -1) // if already served
		return;

        new ran = GetRandomInt(0,9);
        new start = ran;
        while (build_used[ran])
        {
                ran = (ran + 1) % 10;  //search a no used build
                if (ran == start)     //avoid busy loop
                        return;
        }

        build_used[ran] = true;

	sub_debug("Serve %N with build %d", client, ran);

	CheatCommand(client, "give", "first_aid_kit")
	CheatCommand(client, "give", "pain_pills");
	
	/*give weapon */
	new val = GetConVarInt(build[ran]);
	switch(val)
	{
		case SHOTGUN:
		{
			CheatCommand(client, "give", "autoshotgun");
		}
		case SNIPE:
		{
			CheatCommand(client, "give", "hunting_rifle")
		}
		case GL:
		{
			CheatCommand(client, "give", "grenade_launcher")
		}
		case AK47:
		{
			CheatCommand(client, "give", "rifle_ak47")
		}
		case RIFLE:
		{
			CheatCommand(client, "give", "rifle")
		}		
	}

	/*now give melee or deagle*/
	new second = GetRandomInt(0,9);
	new start_second = second;
	while(build_second[second] == -1)
	{
		second = (second + 1) % 10;
		if(second == start_second) //avoid busy loop
			return;
	}

	sub_debug("giving to %N : %d", client, build_second[second]);
	if(build_second[second] == MELEE)
	{
		give_random_melee(client);	
	}
	else if(build_second[second] == DEAGLE)
	{
		CheatCommand(client, "give", "pistol_magnum")
	}

	build_second[second] = -1; //mark this melee given

}


public give_random_melee(any:Client)
{

	decl String:ScriptName[32];
	new rand = GetRandomInt(0,8);

	switch(rand)
	{
		case 0:
		{
			GetScriptName( "golfclub", ScriptName );
			GiveMelee(Client,ScriptName, "golfclub");
		}
		case 1:
		{
			GetScriptName( "fireaxe", ScriptName );
			GiveMelee(Client,ScriptName, "fireaxe");
		}
		case 2:
		{
			GetScriptName( "frying_pan", ScriptName );
			GiveMelee(Client,ScriptName, "frying_pan");
		}
		case 3:
		{
			GetScriptName( "machete", ScriptName );
			GiveMelee(Client,ScriptName, "machete");
		}
		case 4:
		{
			GetScriptName( "baseball_bat", ScriptName );
			GiveMelee(Client,ScriptName, "baseball_bat");
		}
		case 5:
		{
			GetScriptName( "crowbar", ScriptName );
			GiveMelee(Client,ScriptName, "crowbar");
		}
		case 6:
		{
			GetScriptName( "tonfa", ScriptName );
			GiveMelee(Client, ScriptName, "tonfa");
		}
		case 7:
		{
			GetScriptName( "katana", ScriptName );
			GiveMelee(Client, ScriptName, "katana");
		}
		case 8:
		{
			GetScriptName( "electric_guitar", ScriptName );
			GiveMelee(Client,ScriptName, "electric_guitar");
		}
		default:
		{
			sub_debug("Get invalid melee %d", rand);
		}
	}
}

/* use cheatcommand to give melee */
GiveMelee(Client,const String:Class[32], const String:Item[32])
{
	new MeleeSpawn = CreateEntityByName( "weapon_melee" );
	DispatchKeyValue( MeleeSpawn, "melee_script_name", Class );
	CheatCommand(Client, "give", Item);

}

/* these 2 function are from Melee In Saferoom, allow to spawn every melee on each map*/
stock GetMeleeClasses()
{
	new MeleeStringTable = FindStringTable( "MeleeWeapons" );
	g_iMeleeClassCount = GetStringTableNumStrings( MeleeStringTable );
	
	for( new i = 0; i < g_iMeleeClassCount; i++ )
	{
		ReadStringTable( MeleeStringTable, i, g_sMeleeClass[i], 32 );
	}	
}

stock GetScriptName( const String:Class[32], String:ScriptName[32] )
{
	for( new i = 0; i < g_iMeleeClassCount; i++ )
	{
		if( StrContains( g_sMeleeClass[i], Class, false ) == 0 )
		{
			Format( ScriptName, 32, "%s", g_sMeleeClass[i] );
			return;
		}
	}
	Format( ScriptName, 32, "%s", g_sMeleeClass[0] );	
}
